﻿using System;
using System.Collections.ObjectModel;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Bymed.RegistrationCodeManager.Service.Shared;
using Miris.HumanMilkAnalyser.DataModel;
using Miris.HumanMilkAnalyser.Service;
using Miris.HumanMilkAnalyser.WPF.Model;
using Miris.HumanMilkAnalyser.WPF.Shared;
using Miris.HumanMilkAnalyser.Service.Shared;

namespace Miris.HumanMilkAnalyser.WPF.ViewModel
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// See http://www.galasoft.ch/mvvm
    /// </para>
    /// </summary>
    public class RegistrationCodeViewModel : MyViewModelBase
    {
        private RegistrationCodeConfigurationService _registrationCodeConfigurationService;

        /// <summary>
        /// Initializes a new instance of the RegistrationCodeViewModel class.
        /// </summary>
        public RegistrationCodeViewModel(IDataService dataService)
            : base(dataService)
        {
            _registrationCodeConfigurationService = ServiceFactory.CreateRegistrationCodeConfigurationService();
        }

        public override void ResetProperties()
        {
            try
            {
                base.ResetProperties();

                SetProperties(_registrationCodeConfigurationService.Load());
            }
            catch (Exception ex)
            {
                RequestDisplayErrorMessage(ex.Message);
            }
        }

        /// <summary>
        /// The <see cref="ComputerNumber" /> property's name.
        /// </summary>
        public const string ComputerNumberPropertyName = "ComputerNumber";

        private string _computerNumber = string.Empty;

        /// <summary>
        /// Sets and gets the ComputerNumber property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string ComputerNumber
        {
            get
            {
                return _computerNumber;
            }

            set
            {
                if (_computerNumber == value)
                {
                    return;
                }

                RaisePropertyChanging(ComputerNumberPropertyName);
                _computerNumber = value;
                RaisePropertyChanged(ComputerNumberPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="RegistrationCode" /> property's name.
        /// </summary>
        public const string RegistrationCodePropertyName = "RegistrationCode";

        private string _registrationCode = string.Empty;

        /// <summary>
        /// Sets and gets the RegistrationCode property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string RegistrationCode
        {
            get
            {
                return _registrationCode;
            }

            set
            {
                if (_registrationCode == value)
                {
                    return;
                }

                RaisePropertyChanging(RegistrationCodePropertyName);
                _registrationCode = value;
                RaisePropertyChanged(RegistrationCodePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="AvailableAuthorisedUsage" /> property's name.
        /// </summary>
        public const string AvailableAuthorisedUsagePropertyName = "AvailableAuthorisedUsage";

        private string _availableAuthorisedUsage = string.Empty;

        /// <summary>
        /// Sets and gets the AvailableAuthorisedUsage property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string AvailableAuthorisedUsage
        {
            get
            {
                return _availableAuthorisedUsage;
            }

            set
            {
                if (_availableAuthorisedUsage == value)
                {
                    return;
                }

                RaisePropertyChanging(AvailableAuthorisedUsagePropertyName);
                _availableAuthorisedUsage = value;
                RaisePropertyChanged(AvailableAuthorisedUsagePropertyName);
            }
        }

        private RelayCommand _saveCommand;

        /// <summary>
        /// Gets the SaveCommand.
        /// </summary>
        public RelayCommand SaveCommand
        {
            get
            {
                return _saveCommand ?? (_saveCommand = new RelayCommand(
                    ExecuteSaveCommand,
                    CanExecuteSaveCommand));
            }
        }

        private bool CanExecuteSaveCommand()
        {
            var canSave = true;

            if (string.IsNullOrEmpty(RegistrationCode.Trim()) ||
                RegistrationCodeManagerUtility.DecryptRegistrationCode(RegistrationCode) == null)
            {
                canSave = false;
            }

            return canSave;
        }

        private void ExecuteSaveCommand()
        {
            try
            {
                MiniLogHelper.SyncMiniLogFileFromDevice();
                Save();
                RequestGotoPage(new MainPage());
            }
            catch (Exception ex)
            {
                RequestDisplayErrorMessage(ex.Message);
            }
        }

        /// <summary>
        /// Save current device configuration
        /// </summary>
        private void Save()
        {
            var availableAuthorisedUsageCount = RegistrationCodeManagerUtility.DecryptRegistrationCode(RegistrationCode).AuthorisedUsageCount;

            var entity = new RegistrationCodeConfiguration
            {
                RegistrationCode = RegistrationCode,
                AvailableAuthorisedUsageCount = RegistrationCodeManagerUtility.EncryptString(availableAuthorisedUsageCount.ToString())
            };

            _registrationCodeConfigurationService.Save(entity);
        }

        /// <summary>
        /// Set current all properties based on provided instance of DeviceConfiguration.
        /// </summary>
        /// <param name="entity">The instance of DeviceConfiguration that contains all data.</param>
        private void SetProperties(RegistrationCodeConfiguration entity)
        {
            ComputerNumber = entity.ComputerNumber;
            RegistrationCode = entity.RegistrationCode;

            SetAvailableAuthorisedUsage(entity.RegistrationCode, entity.AvailableAuthorisedUsageCount);
        }

        /// <summary>
        /// Set the AvailableAuthorisedUsage based on saved RegistrationCode and AvailableAuthorisedUsageCount.
        /// </summary>
        /// <param name="registrationCode">The saved and decrypted RegistrationCode.</param>
        /// <param name="availableAuthorisedUsageCount">The saved and decrypted AvailableAuthorisedUsageCount.</param>
        private void SetAvailableAuthorisedUsage(string registrationCode, string availableAuthorisedUsageCount)
        {
            var genuineCheckService = new GenuineCheckService();
            var currentDeviceSerialNumber = genuineCheckService.GetSerialNumber();
            var currentComputerName = genuineCheckService.GetComputerName();
            var decryptedRegistrationCode = RegistrationCodeManagerUtility.DecryptRegistrationCode(registrationCode);

            if (decryptedRegistrationCode == null)
            {
                AvailableAuthorisedUsage = "无效注册码，错误代码001。";
            }
            else if (currentComputerName != decryptedRegistrationCode.ComputerNumber)
            {
                AvailableAuthorisedUsage = "无效注册码，错误代码002。";
            }
            else if (currentDeviceSerialNumber != decryptedRegistrationCode.DeviceNumber)
            {
                AvailableAuthorisedUsage = "无效注册码，错误代码003。";
            }
            else if (availableAuthorisedUsageCount == "0")
            {
                AvailableAuthorisedUsage = "无效注册码，错误代码004。";
            }
            else if (availableAuthorisedUsageCount == "-1")
            {
                AvailableAuthorisedUsage = "无限制";
            }
            else
            {
                AvailableAuthorisedUsage = availableAuthorisedUsageCount;
            }
        }
    }
}